package cn.haocxy.jfm.file;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


/**
 * <p>剪切板
 * <p>
 * 剪切板的一次完整使用周期总是以设置模式开始(setMode), 
 * 然后添加元素(add), 最后一次性取走所有元素(retriveAll).
 * <p>
 * 也可以在周期结束前( 即不添加元素或取走元素 )直接设置模式,
 * 使得剪切板中的当前内容被丢弃, 开始一轮新的周期.
 * <p>
 * 但只要想添加元素或设置元素,就必须先设置模式.
 * @author 蔡心宇
 *
 */
public class Clipboard {

	/**
	 * <p>剪切板所处的模式
	 * 
	 * <p>COPY: 复制模式(复制+粘贴)
	 * <p>MOVE: 移动模式(剪切+粘贴)
	 * <p>EMPTY: 剪切板中无内容
	 * 
	 * @author 蔡心宇
	 *
	 */
	public static enum Mode {
		BAD, COPY, MOVE
	}
	
	// 剪切板当前的模式
	private Mode mode = Mode.BAD;
	
	// 剪切板中的内容
	private List<FilePath> content = new ArrayList<>();
	
	private static Clipboard obj = null;
	
	private Clipboard() {
	}
	
	public static Clipboard get() {
		if (obj == null) {
			synchronized (Clipboard.class) {
				if (obj == null) {
					obj = new Clipboard();
				}
			}
		}
		return obj;
	}
	
	/**
	 * 设置剪切板模式, 同事清空剪切板内容
	 * @param mode
	 * @return
	 */
	public synchronized Clipboard setMode(Mode mode) {
		this.mode = mode;
		if (!mode.equals(Mode.BAD)) {
			content = new ArrayList<>();
		} else {
			content = null;
		}
		return this;
	}
	
	/**
	 * 查询当前模式
	 * @return
	 */
	public synchronized Mode getMode() {
		return mode;
	}
	
	public synchronized boolean isEmpty() {
		return content == null || content.isEmpty();
	}
	
	// 检查模式是否为EMPTY, 如果为EMPTY则无法添加元素和获取元素
	private synchronized void checkMode() {
		if (mode.equals(Mode.BAD)) {
			throw new IllegalStateException("Current mode is BAD.");
		}
	}
	
	public synchronized void clear() {
		retriveAll();
	}
	
	/**
	 * 向剪切板添加一项文件
	 * <p>
	 * 如果要添加较多的文件, 则请使用参数为容器的版本, 因为每次调用这个方法都要检查状态, 效率较低.
	 * 
	 * @param path
	 */
	public synchronized void add(FilePath path) {
		checkMode();
		if (path == null) {
			throw new NullPointerException("path should not be null.");
		}
		content.add(path);
	}
	
	/**
	 * 向剪切板添加一批文件
	 * 
	 * @param paths
	 */
	public synchronized void add(Collection<FilePath> paths) {
		checkMode();
		if (paths == null) {
			throw new NullPointerException("paths should not be null.");
		}
		content.addAll(paths);
	}
	
	/**
	 * 返回并移除所有剪切板中的元素
	 * @return
	 */
	public synchronized List<FilePath> retriveAll() {
		List<FilePath> tmp = content;
		content = null;
		return tmp;
	}
}
